//
//  IMB_NetWorkAcessOperation.m
//  InvestChina
//
//  Created by 闫建刚 on 14-3-30.
//  Copyright (c) 2014年 iMobile. All rights reserved.
//

#import "IMB_NetWorkAcessOperation.h"

@interface IMB_NetWorkAcessOperation()<NSURLConnectionDataDelegate>
{
    /**
     *  url字符串
     */
    NSString *urlStr_;
    
    /**
     * 请求方法："GET"/"POST"
     */
    NSString *requestMethod_;
    
    
    /**
     *  网络连接对象
     */
    NSURLConnection *connect_;
    
    
    // 请求对象
    NSMutableURLRequest *request_;
    
}

/**
 *  根据响应状态码获取数据响应错误消息
 *
 *  @param statusCode 状态码
 *
 *  @return 访问错误
 */
- (NSString*)responseErrMsgForStatusCode:(long)statusCode;

/**
 *  根据网络请求错误码返回错误消息
 *
 *  @param errorCode 网络错误代码
 *
 *  @return 错误消息
 */
- (NSString*)netErrorrMsgForCode:(NSInteger)errorCode;

/**
 *  从缓存读取数据，同时提示错误信息
 *
 *  @param errorMessage 错误消息
 */
- (void)readDataFromCacheWithErrMsg:(NSString*)errorMessage;

@end


@implementation IMB_NetWorkAcessOperation

#pragma mark - Extend method

// 根据网络请求错误码返回错误消息
- (NSString*)netErrorrMsgForCode:(NSInteger)errorCode{
    switch (errorCode) {
        case kCFURLErrorBadURL:
            return CONNECTION_ERROR_MSG_FOR_BAD_URL;
            break;
        case kCFURLErrorTimedOut:
            return CONNECTION_ERROR_MSG_FOR_TIME_OUT;
            break;
        case kCFURLErrorUnsupportedURL:
            return CONNECTION_ERROR_MSG_FOR_UNSUPPORT_URL;
            break;
        case kCFURLErrorCannotFindHost:
            return CONNECTION_ERROR_MSG_FOR_NOT_FIND_HOST;
            break;
        default:
            NSLog(@"###### 未知netErrorCode:%ld",(long)errorCode);
            return CONNECTION_ERROR_MSG_FOR_UNKNOW;
            break;
    }
    return nil;
}

// 根据响应状态码获取数据响应错误消息
- (NSString*)responseErrMsgForStatusCode:(long)statusCode{
    
    if (statusCode > ENUM_HTTP_STATUS_NET_IF_SERVER_EXCEPTION) {
        return NET_ERROR_MSG_FOR_NET_IF_EXCEPTION;
    }
    switch (statusCode) {
        case ENUM_HTTP_STATUS_NET_IF_REQUEST_METHOD_ERROR:
            return NET_ERROR_MSG_FOR_NET_IF_REQUEST_METHOD_ERROR;
            break;
        case ENUM_HTTP_STATUS_NET_IF_NOT_EXIST:
            return NET_ERROR_MSG_FOR_NET_IF_NOT_EXIST;
            break;
        case ENUM_HTTP_STATUS_NET_IF_NOT_IMP:
            return NET_ERROR_MSG_FOR_NET_IF_NOT_IMP;
            break;
        case ENUM_HTTP_STATUS_OK:
            return nil;
        default:
            NSLog(@"###### 未知statusCode:%ld",statusCode);
            return NET_ERROR_MSG_FOR_HTTP_STATUS_UNKNOW;
            break;
    }
    
    return nil;
}



/**
 *  网络访问完毕
 */
- (void)netAccessComplete{
    dispatch_sync(dispatch_get_main_queue(), ^{
        
        // add by jason yan 2014-05-29
        [self willChangeValueForKey:@"isFinished"];
        [self willChangeValueForKey:@"isExecuting"];
        
        block_(responseData_,message_);
        
        // add by jason yan 2014-05-29
        executing_ = NO;
        finished_ = YES;
        [self didChangeValueForKey:@"isExecuting"];
        [self didChangeValueForKey:@"isFinished"];
    });
}

#pragma mark - NSURLConnectionDataDelegate method

/**
 *  网络请求失败处理
 *
 *  @param connection 网络连接对象
 *  @param error      错误封装
 */
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
#warning 开发阶段使用系统错误提示，发布前替换
    //message_ = [error description];
    
    // add by jason yan 2014-05-29
    request_.cachePolicy = NSURLRequestReturnCacheDataElseLoad;
    
    message_ = [self netErrorrMsgForCode:error.code];
    
    // update by jason yan 2014-05-29
    
    [self readDataFromCacheWithErrMsg:message_];
    //[self netAccessComplete];
}

/**
 *  已接受到网络响应
 *
 *  @param connection 网络连接对象
 *  @param response   响应对象
 */
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
    NSHTTPURLResponse *httpUrlResponse = (NSHTTPURLResponse*)response;
    NSString *responseErrMsg = [self responseErrMsgForStatusCode:httpUrlResponse.statusCode];
    if (responseErrMsg) {
        message_ = responseErrMsg;
    }else{
        responseData_ = [NSMutableData data];
    }
}

/**
 *  接收到网络数据
 *
 *  @param connection 网络连接对象
 *  @param data       网络数据
 */
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    [responseData_ appendData:data];
}

/**
 *  已结束网络加载
 *
 *  @param connection 网络连接对象
 */
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
    [self netAccessComplete];
}

/**
 *  将要缓存响应数据
 *
 *  @param connection     网络连接对象
 *  @param cachedResponse 缓存响应对象
 *
 *  @return 缓存响应对象
 */
- (NSCachedURLResponse*)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse{
    // update by jason yan 2014-05-29
    /*NSLog(@"已缓存数据");
    return cachedResponse;*/
    
    if ([self canCacheData:cachedResponse]) {
        NSLog(@"已缓存数据");
        return cachedResponse;
    }
    NSLog(@"不缓存无效数据");
    return nil;
}

#pragma mark - Interface method

/**
 *  取消网络请求
 */
- (void)cancelNetAccess{
    [connect_ cancel];
}


#pragma mark - Life Cycle method

- (void)dealloc{
    NSLog(@"NetWorkAccesOperation delloc...");
}

- (id)initWithUrlStr:(NSString *)urlStr requestMethod:(NSString *)method paramsValues:(NSDictionary *)paramsDict completeHandler:(DidFinishRequestHandler)block{
    if (self = [super init]) {
        urlStr_ = urlStr;
        requestMethod_ = method;
        paramsDict_ = paramsDict;
        block_ = block;
    }
    return self;
}

/**
 *  实现NSOperation的mian方法
 */
- (void)main{
    @autoreleasepool {
        
        NSMutableString *mutableUrlStr = [NSMutableString stringWithString:urlStr_];
        
        NSMutableString *paramsStr = [NSMutableString string];
        if (paramsDict_) {
            if ([requestMethod_ isEqualToString:NET_REQUEST_GET]) {
                [paramsStr appendString:@"?"];
            }
            for (NSString *key in paramsDict_) {
                [paramsStr appendString:key];
                [paramsStr appendString:@"="];
                [paramsStr appendString:[paramsDict_[key] encodedURLForUTF8]];
                [paramsStr appendString:@"&"];
            }
            [paramsStr deleteCharactersInRange:NSMakeRange(paramsStr.length - 1, 1)];
            
        }
        if ([requestMethod_ isEqualToString:NET_REQUEST_GET]) {
            [mutableUrlStr appendString:paramsStr];
        }
        NSURL *url = [NSURL URLWithString:mutableUrlStr];
        NSLog(@"%@",url);
        
        // update by jason yan 2014-05-29
        request_ = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:NET_REQUEST_TIME_OUT];
        
        request_.HTTPMethod = requestMethod_;
        
        if ([requestMethod_ isEqualToString:NET_REQUEST_POST]) {
            request_.HTTPBody = [paramsStr dataUsingEncoding:NSUTF8StringEncoding];
        }
        
        if ([IMB_NetUtils isNetConnect]) {
            request_.cachePolicy = NSURLRequestUseProtocolCachePolicy;
        }else{
            if (!IS_IOS_7) {
                [self readDataFromCacheWithErrMsg:CONNECTION_ERROR_MSG_FOR_NET_SET];
                return;
            }
            message_ = CONNECTION_ERROR_MSG_FOR_NET_SET;
        }
        connect_ = [NSURLConnection connectionWithRequest:request_ delegate:self];
        
        [[NSRunLoop currentRunLoop]runUntilDate:[NSDate distantFuture]];
        
        
        /*NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:NET_REQUEST_TIME_OUT];
        request.HTTPMethod = requestMethod_;
        
        if ([requestMethod_ isEqualToString:NET_REQUEST_POST]) {
            request.HTTPBody = [paramsStr dataUsingEncoding:NSUTF8StringEncoding];
        }
        connect_ = [NSURLConnection connectionWithRequest:request delegate:self];
        
        [[NSRunLoop currentRunLoop]runUntilDate:[NSDate distantFuture]];*/
        
    }
}

// 从缓存获取数据,同时提示错误信息
- (void)readDataFromCacheWithErrMsg:(NSString*)errorMessage{
    NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache]cachedResponseForRequest:request_];
    if (cachedResponse != nil &&
        [[cachedResponse data] length] > 0)
    {
        responseData_ = [NSMutableData dataWithData:[cachedResponse data]];
    }
    message_ = errorMessage;
    [self netAccessComplete];
}

//#warning 子类需重写此方法
- (BOOL)canCacheData:(NSCachedURLResponse *)cachedResponse{
    return YES;
}

#pragma mark - Override NSOperation method

- (void)start {
    // Always check for cancellation before launching the task.
    if ([self isCancelled])
    {
        // Must move the operation to the finished state if it is canceled.
        [self willChangeValueForKey:@"isFinished"];
        finished_ = YES;
        [self didChangeValueForKey:@"isFinished"];
        return;
    }
    
    // If the operation is not canceled, begin executing the task.
    [self willChangeValueForKey:@"isExecuting"];
    [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];
    executing_ = YES;
    [self didChangeValueForKey:@"isExecuting"];
}

- (BOOL)isConcurrent {
    return YES;
}

- (BOOL)isExecuting {
    return executing_;
}

- (BOOL)isFinished {
    return finished_;
}


@end
